package dsproject;

import java.io.Serializable;
import java.util.HashSet;

public class Request implements Serializable {

    private Path path;
    private Message message;
    private final int id;

    public int getId() {
        return id;
    }

    /**
     * A request is a container for each sub message forwarded from source to destination (reverse side included)
     * @param path  The one-way path of the request
     * @param rsNeed What kind of resource the mesage ask for
     * @param id The identifier of the request, no real utility for programming, here we use java reference.
     */
    public Request(Path path, HashSet<ResourceState.TYPE> rsNeed, int id, Message.TYPE mtype) {

        HashSet<ResourceState> body = new HashSet<ResourceState>();
        this.path = path;
        for (ResourceState.TYPE type : rsNeed) {
            body.add(new ResourceState(path.getDestination(), type));
        }
        this.id = id;
        this.message = new Message(0, this, body, new HashSet<ResourceState>(), mtype);
    }

    public Message getMessage() {
        return message;
    }

    /**
     * Make the message go forward in its logical way
     * @param currentLoop Used for TTL filters purpose
     * @return the bandwidth used for this operation
     */
    public int operate(int currentLoop, Simulator.TYPE  type) {
        //Sent the message to the following node
        Node sender = this.path.getPosition();
        this.path.next().rcvPacket(message, currentLoop, type, sender);

        //Count the size of the message broadcated, except if for the first step (the source create the message, nothing is broadcast)
        return (this.path.getStatus() == Path.pathStatus.STARTING ? 0 : this.message.getSize());
    }

    /**
     *
     * @return whether or not the request is done
     */
    public Boolean isCompleted() {
        return path.getStatus() == Path.pathStatus.COMPLETED;
    }

    public boolean isAnswered() {
        return path.getStatus() == Path.pathStatus.ANSWERED || path.getStatus() == Path.pathStatus.COMPLETED;
    }
    /**
     *
     * @return the next node
     */
    public Node getNext() {
        return path.getNext();
    }

    public void notifyFound(){
        path.changeDirection();
    }

    @Override
    public String toString(){
        return this.id + "(" + this.path.getPosition() + ":" + this.path.getSource()+ (this.path.getDirection() ? "->" : "<-") + this.path.getDestination() + ") ";
    }
}
